package org.semanticflash.rdf.io.rdfjson
{
	
	
	import com.adobe.serialization.json.JSON;
	import com.bigflexlib.utils.AsyncRunner;
	import com.bigflexlib.x.mx.logging.Log.LogUtil;
	
	import mx.logging.ILogger;
	
	import org.semanticflash.rdf.io.AbstractRDFParser;
	import org.semanticflash.rdf.io.IRDFHandler;
	import org.semanticflash.rdf.values.IRI;
	import org.semanticflash.rdf.values.RDFLangLiteral;
	import org.semanticflash.rdf.values.RDFPlainLiteral;
	import org.semanticflash.rdf.values.RDFTypedLiteral;
	import org.semanticflash.rdf.values.RDFValue;


	/**
	 * 
	 * 
	 * http://n2.talis.com/wiki/RDF_JSON_Specification
	 * 
	 * 
	 * @author aldo.bucchi@gmail.com
	 * 
	 */
	public class RDFJSONParser extends AbstractRDFParser
	{
		
		
		
		private static const URI		:String = "uri";
		
		private static const BNODE	:String = "bnode";
		
		private static const LITERAL	:String = "literal";
		
		
		
		
		
		private var logger:ILogger;



		public function RDFJSONParser( input:*, rdfHandler:IRDFHandler, baseURL:String = null  )
		{
			logger = LogUtil.getStandardLogger( this );
			super( input, rdfHandler, baseURL );
		}
		
		
		
		
		override protected function start( ):void
		{

			var sMap:Object = JSON.decode( input );					

			for ( var s:String in sMap )
			{
				AsyncRunner.queue( parseS, [ s , sMap[s] ] );
			}
		
		}
		
		
		
		private function parseS( s:String, pMap:Object ):void
		{
			
			var subject:IRI;
			
			if ( s.charAt( 0 ) == "_" )
				subject = getBNode( s.substr( 2 ) );
			else
				subject = IRI.instance( s );	
			
			
			for ( var p:String in pMap )
			{
				parseP( subject, p, pMap[p] );	
			}
		
		}
		
		
		
		private function parseP( subject:IRI, p:String, oArray:Array ):void
		{
			
			var predicate:IRI = IRI.instance( p );
			
			for each ( var o:Object in oArray )
			{
				assertStatement( subject, predicate, o2value( o ) );								
			}	
		
		}
		
		
		
		
		
		private function o2value( o:Object ):RDFValue
		{
		
			switch ( o.type )
			{
				
				case URI:
				
					return IRI.instance( o.value );
				
				break;
			

				case BNODE:

					return getBNode( o.value.substr( 2 ) )
					
				break;


				case LITERAL:
				
					if ( o.lang )
						return RDFLangLiteral.instance( o.value, o.lang );
					
					if ( o.datatype )
						return RDFTypedLiteral.instance( o.value, o.datatype );
					
					
					return RDFPlainLiteral.instance( o.value );
				
				break;
			
			}
			
			return null; // TODO: yield error
		
		}
		
	}
}